<template>
	<view class="xiaopao-record-box">
		<view class="xiaopao-record-time">{{formData.showTime || '00:00:00'}}</view>
		<view class="xiaopao-record-act">
			<view
				class="xiaopao-record-btn"
				:class="formData.isRecording ? 'start' : ''"
				@touchstart="onTouchStart"
				@touchend="onTouchEnd"
				@touchmove="onTouchMove"
			></view>
			<view v-if="formData.tempFilePath" class="xiaopao-record-recordBtn" @click="doPlayAudio">
				<template v-if="formData.isPlay">
					<image class="icon" src="./static/video.gif"></image>
				</template>
				<template v-else>
					<image class="icon" src="./static/video.png"></image>
				</template>
			</view>
		</view>
		<view class="xiaopao-record-txt">{{formData.isRecording ? recordTxt : startTxt}}</view>
	</view>
</template>

<script>
	export default {
		name: "xiaopao-record",
		props: {
			startTxt: {
				type: String,
				default: '按住说话'
			},
			recordTxt: {
				type: String,
				default: '松手保存，上移取消'
			},
			noSupportTxt: {
				type: String,
				default: '暂不支持录音'
			},
			modalTitle: {
				type: String,
				default: '提示'
			},
			modalContent: {
				type: String,
				default: '是否要开启麦克风权限？'
			},
			authorizedTxt: {
				type: String,
				default: '请允许使用或在系统设置中打开麦克风权限'
			}
		},
		data() {
			return {
				recorderManager: null, // 录音对象
				formData: this.clearFormData(), // 相关参数
				touchObj: null, // 记处理长按问题
				timekeepingObj: null // 计时对象
			}
		},
		created() {
			this.$nextTick(() => {
				// #ifndef H5
				this.recorderManager = uni.getRecorderManager()
				this.recorderManager.onStop((res) => {
					if (!this.formData.isAuthorized) return
					this.formData.isRecording = false
					this.formData.tempFile = res
					this.formData.tempFilePath = res.tempFilePath
					// 如果上移了，需要取消
					if (this.formData.moveStartY - this.formData.moveEndY > 80) {
						this.formData = this.clearFormData()
					} else {
						this.$emit('cbResult', this.formData)
					}
				})
				// #endif
			})
		},
		methods: {
			// 参数
			clearFormData() {
				const obj = {
					isRecording: false, // 是否录制中
					tempFilePath: '', // 录音源
					showTime: '', // 时长 展示值
					duration: 0, // 时长 秒数
					isPlay: false, // 是否为音频播放中
					tempFile: null, // 选择需要上传的源
					isAuthorized: true ,// 录音是否已授权
					moveStartY: 0, // 按住时，手所按在页面的Y值
					moveEndY: 0 // 树松开时，手所按在页面的Y值
				}
				return obj
			},
			// 按住时 - 长按模式
			onTouchStart (e) {
				this.touchObj = setTimeout(() => {
					this.doStartRecord(e)
				}, 500)
			},
			// 开始录音
			async doStartRecord(e) {
				// #ifdef H5
				uni.showToast({
					icon: 'none',
					title: this.noSupportTxt
				})
				// #endif
				// #ifndef H5
				await this.doRePlayAudio()
				this.formData = this.clearFormData()
				this.$emit('cbClearResult', this.formData)
				this.$emit('cbPermissionTips') // 安卓审核隐私协议需要，使用音频的提示语言,或者直接在字段authorizedTxt处理也可以
				this.recorderManager.start()
				// #ifdef APP || MP-WEIXIN
				const getAuthorized = await uni.getAppAuthorizeSetting().microphoneAuthorized
				if (uni.getSystemInfoSync().platform === 'ios') {
					// iOS时 当表示请求授权被拒绝后才进行展示
					if (getAuthorized === 'denied') {
						this.formData.isAuthorized = false
						return uni.showModal({
							title: this.modalTitle,
							content: this.modalContent,
							success(res) {
								if (res.confirm) {
									 uni.openAppAuthorizeSetting()
								}
							},
						})
					}
				} else if (getAuthorized !== 'authorized') {
					// 由于系统兼容问题，除iOS外其他表示未获得授权时 调用都会有这提示
					this.formData.isAuthorized = false
					return uni.showToast({
						icon: 'none',
						duration: 3000,
						title: this.authorizedTxt
					})
				}
				// #endif
				if (e.touches.length) {
					const getY = Number(e.touches[0]['pageY'])
					this.formData.moveStartY = getY
					this.formData.moveEndY = getY
				}
				this.formData.isRecording = true
				this.doStartTimekeeping()
				// #endif
			},
			// 重置
			doRePlayAudio() {
				if (this.innerAudioContext) {
					try {
						this.formData.isPlay = false
						this.innerAudioContext.pause()
						this.innerAudioContext.destroy()
						this.innerAudioContext = null
					} catch (e) {}
				}
			},
			// 开始计时
			async doStartTimekeeping() {
				await this.doEndTimekeeping()
				let setdSeconds = 0
				this.timekeepingObj = setInterval(() => {
					setdSeconds += 1
					this.formData.duration = setdSeconds
					this.formData.showTime = this.formatTtime(setdSeconds)
				}, 1000)
			},
			// 格式化展示的时长
			formatTtime (time) {
				if (typeof time !== 'number' || time < 0) {
					return time
				}
				let hour = parseInt(time / 3600)
				time = time % 3600
				let minute = parseInt(time / 60)
				time = parseInt(time % 60)
				let second = time
				return ([hour, minute, second]).map(function(n) {
					n = n.toString()
					return n[1] ? n : '0' + n
				}).join(':')
			},
			// 移动时
			onTouchMove (e) {
				e.touches.length && (this.formData.moveEndY = Number(e.touches[0]['pageY']))
			},
			// 松开时
			async onTouchEnd (e) {
				await this.doClearTouchObj()
				this.doEndRecord()
			},
			// 清除定时器 处理防止误触
			doClearTouchObj () {
				this.touchObj && clearTimeout(this.touchObj)
			},
			// 结束录音
			doEndRecord() {
				// #ifdef APP || MP-WEIXIN
				this.doEndTimekeeping()
				this.recorderManager.stop()
				this.formData.isRecording = false
				// #endif
			},
			// 结束计时
			doEndTimekeeping() {
				this.timekeepingObj && clearInterval(this.timekeepingObj)
			},
			// 播放音色
			async doPlayAudio() {
				if (this.formData.isPlay) {
					return this.doPlayPause()
				}
				await this.doRePlayAudio()
				this.innerAudioContext = uni.createInnerAudioContext()
				this.innerAudioContext.autoplay = true
				this.innerAudioContext.src = this.formData.tempFilePath
				this.innerAudioContext.onPlay(() => {
					this.formData.isPlay = true
				})
				this.innerAudioContext.onEnded(() => {
					this.formData.isPlay = false
				})
			},
			// 暂停音色
			doPlayPause() {
				this.innerAudioContext.pause()
				this.formData.isPlay = false
			}
		},
		// 页面销毁时
		beforeUnmount () {
			this.doClearTouchObj()
			this.doEndTimekeeping()
		}
	};
</script>

<style scoped>
	.xiaopao-record-box {
		padding: 24rpx;
	}
	.xiaopao-record-time {
		text-align: center;
		margin-bottom: 24rpx;
		color: #333;
	}
	.xiaopao-record-act {
		display: flex;
		align-items: center;
		flex-direction: column;
		position: relative;
	}
	.xiaopao-record-btn {
		position: relative;
		margin-bottom: 24rpx;
		background-image: url(./static/btn.png);
		background-repeat: no-repeat;
		background-size: 100% auto;
		width: 80rpx;
		height: 80rpx;
		border-radius: 50%;
	}
	.xiaopao-record-btn.start {
		background-image: url(./static/btn-focus.png);
		animation: runScale 1s linear infinite;
	}
	.xiaopao-record-btn .icon {
		width: 80rpx;
		height: 80rpx;
	}
	.xiaopao-record-txt {
		text-align: center;
		font-size: 24rpx;
		color: #777;
	}
	.xiaopao-record-recordBtn {
		position: absolute;
		top: 0;
		right: 0;
		padding: 24rpx;
	}
	.xiaopao-record-recordBtn .icon {
		width: 40rpx;
		height: 40rpx;
	}
	@keyframes runScale {
	  from {
	    box-shadow: 0 0 0 0  #f00;
	  }
	  to {
	    box-shadow: 0 0 100rpx 30rpx  #f00;
	  }
	}
</style>